package hz.mobileproject.pda.callroll.manger;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.megvii.facepp.sdk.Facepp;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import hz.mobileproject.pda.callroll.entity.FaceIdEntity;

/**
 * Created by hasee on 2017/10/27.
 * 人脸对比
 * 本地底库离线比对
 */
public class FaceCheckMgr {

    private final static String TAG = FaceCheckMgr.class.getSimpleName();

    public final static int MESSAGE_WHAT_CHECK_SUCCESS = 0;
    public final static int MESSAGE_WHAT_CHECK_HAVE_BEEN = 1;
    public final static int MESSAGE_WHAT_CHECK_CALL_POLICE = 2;

    private static FaceCheckMgr mInstance;

    private Context mContext;

    private ExecutorService mExecutor;

    private int mdSuccessPoint = 95;
    private Handler mHandler;

    private FaceCheckMgr(Context context){
        mContext = context;
        mExecutor = Executors.newFixedThreadPool(4);
    }

    /**
     * 离线检测人脸异步任务
     */
    class CheckFaceOffNetRunnable implements Runnable{

        private Facepp mFaceApp;
        private Facepp.Face mFace;

        public CheckFaceOffNetRunnable(Facepp facepp, Facepp.Face face){
            mFaceApp = facepp;
            mFace = face;
        }

        @Override
        public void run() {
            synchronized (TAG){
                //获取之前加载的脸部数据
                List<FaceIdEntity> list = PhotoFaceLoaderMgr.getInstance(mContext.getApplicationContext()).getFaceList();
                boolean isNeedCallPolice = true;
                List<ScoreAndId> successIndexList = new ArrayList<>();
                for(int i=0;i<list.size();i++){
                    String id = list.get(i).getId();
                    int prisonerStatus = 0;
                    if(null != CallRollByFaceDataMgr.getInstance().getPrisonerListItemById(id)){
                        prisonerStatus = CallRollByFaceDataMgr.getInstance().getPrisonerListItemById(id).getCallRollStatus();
                    }
                    int callRollStatus = list.get(i).getCallRollStatus();
                    double score = mFaceApp.faceCompare(mFace.feature, list.get(i).getFeatureArray());

                    int successPoint = CallRollByFaceDataMgr.getInstance().getSimilarityDegree();
                    if(successPoint <= 0){
                        successPoint = mdSuccessPoint;
                    }

                    if(score >= successPoint){
                        //TODO 人脸识别成功处理
                        Log.i(TAG, "id = " + id + " ,score = "+ score +" ,status = " + callRollStatus + " ,thread = " + Thread.currentThread().getName());
                        isNeedCallPolice = false;
                        if (prisonerStatus != callRollStatus){
                            successIndexList.add(new ScoreAndId(id, score, 3));
                        }else {
                            successIndexList.add(new ScoreAndId(id, score, callRollStatus));
                        }
                    }
                }

                if (isNeedCallPolice){
                    //TODO 该脸不存在，报警处理
                    Log.e(TAG, "call police");
                    sendMesToMain(MESSAGE_WHAT_CHECK_CALL_POLICE, "");
                    return;
                }

                ScoreAndId scoreAndId = compareMaxScoreList(successIndexList);
                int CallRollStatus = scoreAndId.getStatus();
                String id = scoreAndId.getId();
                if (CallRollStatus == 0){//未被点名
                    //将这个犯人数据状态设置为上传中
                    CallRollByFaceDataMgr.getInstance().updateAllPrisonerListItemStatus(id, 1);
                    //将这个脸部数据设置为上传中
                    PhotoFaceLoaderMgr.getInstance(mContext.getApplicationContext())
                            .updataFaceListItemStatusById(id, 1);
                    Log.i(TAG, "face id = "+ id + "success");
                    sendMesToMain(MESSAGE_WHAT_CHECK_SUCCESS, id);
                }else{//已点过名
                    Log.i(TAG, "face id = "+ id + " have been call roll !");
                    sendMesToMain(MESSAGE_WHAT_CHECK_HAVE_BEEN, id);
                }
            }
        }
    }

    public static FaceCheckMgr getInstance(Context context){
        if(null == mInstance){
            mInstance = new FaceCheckMgr(context);
        }
        return mInstance;
    }

    /**
     * 取最大值的元素
     * @param successIndexList
     * @return
     */
    private ScoreAndId compareMaxScoreList(List<ScoreAndId> successIndexList){
        ScoreAndId tempScoreAndId = new ScoreAndId("", 0, 0);
        for (int i=0;i<successIndexList.size();i++){
            if (successIndexList.get(i).getScore() > tempScoreAndId.getScore()){
                tempScoreAndId.setScore(successIndexList.get(i).getScore());
                tempScoreAndId.setId(successIndexList.get(i).getId());
                tempScoreAndId.setStatus(successIndexList.get(i).getStatus());
            }
        }
        return tempScoreAndId;
    }

    private class ScoreAndId{
        String id;
        double score;
        int status;

        public ScoreAndId(String id, double score, int status){
            this.id = id;
            this.score = score;
            this.status = status;
        }
        public int getStatus() {
            return status;
        }

        public void setStatus(int status) {
            this.status = status;
        }
        public double getScore() {
            return score;
        }

        public void setScore(double score) {
            this.score = score;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }
    }

    /**
     * 给主线程回调
     */
    private void sendMesToMain(int what, String id){
        if(mHandler != null){
            Message mes = new Message();
            mes.what = what;
            mes.obj = id;
            mHandler.sendMessage(mes);
        }
    }

    /**
     * 离线检测人脸
     */
    public void checkOffNetFace(Facepp facepp, Facepp.Face face, Handler handler){
        mHandler = handler;
        mExecutor.execute(new Thread(new CheckFaceOffNetRunnable(facepp, face)));
    }

    /**
     * 置空handler，防止内存泄漏
     */
    public void cleanHandler(){
        mHandler = null;
    }

}
